Skip to content

correct: Say why the entry was invalid when suggesting a repair - #101

Closed
BenWestgate wants to merge 13 commits into
codex/remove-unreachable-v1-branchesfrom
claude/new-issue-fixes-fvhbl3-85
Closed

BenWestgate wants to merge 13 commits into
codex/remove-unreachable-v1-branchesfrom
claude/new-issue-fixes-fvhbl3-85

Conversation

@BenWestgate

@BenWestgate BenWestgate commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Requested by Ben · project thread

Problem

correct, and the embedded “Possible correction” prompt in recovery commands, showed a repaired string without first explaining why the entered text was invalid.

Change

Print one Invalid: <reason> line using the parse error already available to the caller. Mixed-case input uses the profile-neutral wording that codex32 strings are all uppercase or all lowercase and both cases decode to the same data. The reason is printed only after the low-discrimination YES gate, so noninteractive gate failure still emits only its operational error.

The tested cases cover mixed case, invalid threshold/index symbols, invalid data characters, and an extra character. create --existing keeps using the library’s own rejection reason.

Review stack

Base: #105 (codex/remove-unreachable-v1-branches) at 361feb7.

The unrelated <5250 cap commit was removed and its old tip is preserved on archive/101-pre-restack-20261004. #105 was merged into this feature branch through stack-maintenance PR #122, so current head 65a886a is an actual descendant of #105. Comparing #105 to the head shows only the four reviewed behavior/test files.

The combined tree is 5,188 installed production logical lines under <5200. Exact-head Python-package run 755 succeeded on this combined head. #104 overlaps the _confirm_correction call shape and must preserve both arguments if #104 is later accepted.

Validation

The behavior commit dc4bf7b has a Codex ACK. Prior validation passed 931 tests plus Ruff, strict mypy and focused optimized tests; exact-head Python-package run 755 is green. The review finding that the original mixed-case wording incorrectly said “same wallet” for non-wallet profiles is fixed.

Closes #85.

AI-assisted stack maintenance and review. Responsible-human review/authorship policy still applies before integration.

@BenWestgate BenWestgate self-assigned this Oct 1, 2026
@BenWestgate
BenWestgate marked this pull request as ready for review October 1, 2026 13:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b4d15aeeb6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/codex32/_cli_input.py Outdated
@BenWestgate
BenWestgate force-pushed the 30-recorded-fingerprint-gate branch 2 times, most recently from a7efaae to 054e8d9 Compare October 1, 2026 22:02
@chatgpt-codex-connector

This comment has been minimized.

@BenWestgate
BenWestgate force-pushed the 30-recorded-fingerprint-gate branch from 054e8d9 to 115f2c2 Compare October 2, 2026 08:57
@BenWestgate
BenWestgate force-pushed the claude/new-issue-fixes-fvhbl3-85 branch from e852899 to dc4bf7b Compare October 2, 2026 17:19
@chatgpt-codex-connector

This comment has been minimized.

1 similar comment
@chatgpt-codex-connector

This comment has been minimized.

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-generated review (Codex), posted at the maintainer's request.

Not ACKing 96ac5aa yet: this raises the installed-code budget from 5,200 to 5,250 without explicit authorization. The invalid-reason UX change otherwise looks sound.

@BenWestgate BenWestgate added cli Command-line interface behavior. correction Correction engine and correction UX. gate: adversarial review Resolve, merge, or explicitly defer before the next full adversarial review. labels Oct 4, 2026
@BenWestgate
BenWestgate force-pushed the claude/new-issue-fixes-fvhbl3-85 branch from 96ac5aa to dc4bf7b Compare October 4, 2026 19:00
@chatgpt-codex-connector

This comment has been minimized.

@BenWestgate
BenWestgate changed the base branch from 30-recorded-fingerprint-gate to codex/remove-unreachable-v1-branches October 4, 2026 19:01

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-generated current-head follow-up review (Codex), posted at the maintainer's request.

ACK dc4bf7bbc223 now that the unrelated <5250 cap commit has been removed.

The invalid-input reason is taken from the parse error the caller already caught, so the change does not add a second parsing/validation path. The message remains behind the existing low-discrimination disclosure gate, and the follow-up wording is profile-neutral (“same data”) rather than incorrectly assuming a wallet. The tested malformed-header/data/length and mixed-case cases cover the intended user-facing boundary.

No correctness blocker found in the focused behavior diff. The PR is stacked on #105 and preserves <5200; run final CI on the actual integrated #105 + #101 tip before freeze. Responsible-human authorship/review policy still applies.

BenWestgate added a commit that referenced this pull request Oct 4, 2026
Temporary stack refresh: bring the reviewed #105 cleanup into #101's feature branch so the PR head and CI represent the intended combined tree. Human integration will rewrite/squash agent-authored history under repository policy.
@chatgpt-codex-connector

This comment has been minimized.

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Codex current-head review at 65a886a: no findings. Since the prior ACK, the only new commit brings in #105’s already exact-head-reviewed cleanup; the invalid-reason behavior and disclosure-gate placement are unchanged.

@BenWestgate BenWestgate left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI-generated current-head stack review (Codex), posted at the maintainer's request.

Code ACK 65a886a735b8 for the actual #105 + #101 head. #105 is now an ancestor of this branch; comparing #105 (361feb7) to the head yields only the four reviewed invalid-reason behavior/test files. The unrelated <5250 cap change is absent.

The reason text still comes from the already-caught parse error, remains behind the existing low-discrimination disclosure gate, and uses profile-neutral mixed-case wording. The known #104 call-shape overlap remains documented if that post-v1 enhancement is later integrated.

Fresh current-head Python-package run #755 is still queued at the time of this review. Treat this as an exact-head code ACK with CI pending. Responsible-human authorship/review still applies before integration.

Copy link
Copy Markdown
Owner Author

V1 disposition (Codex, 2026-10-04): defer this post-audit UX enhancement from the v1 candidate.

The invalid-reason behavior has a current-head Codex code ACK and fits under the library budget on #105. It is not required to close the original mixed-case audit finding, which is already fixed by #42. A temporary attempt to combine #100 and #101 exposed a real late-stack overlap conflict, so carrying this into v1 would enlarge the frozen-candidate review scope without closing an audit finding.

Keep #101 open for post-v1, where it can be rebased with #100/#104 as appropriate. Human authorship/review remains required when integrated.

@BenWestgate
BenWestgate marked this pull request as draft October 4, 2026 19:18
@BenWestgate BenWestgate removed the gate: adversarial review Resolve, merge, or explicitly defer before the next full adversarial review. label Oct 4, 2026
@BenWestgate
BenWestgate force-pushed the codex/remove-unreachable-v1-branches branch 2 times, most recently from 03b0f8a to 9ea48de Compare October 6, 2026 14:29
BenWestgate and others added 13 commits October 6, 2026 22:32
CorrectionEdit was a plain dataclass, so repr() of a correction candidate disclosed each edit's observed and replacement characters. The replacement can be true recovery text.

Exclude those two fields from dataclass repr while preserving explicit field access, equality, hashing, and correction behavior. Add a regression that repairs eight erasures and verifies the candidate representation does not reveal the restored characters.

Fixes #129
core_descriptors(private=False) asked a named Bitcoin Core wallet for its
HD key and built public descriptors from it, but only type-checked the
seed it was given, so a wallet holding a different seed returned that
wallet's descriptors. Nothing calls it: ms32 wallet hands Core the root
xprv with addhdkey and Core builds the descriptors itself with
createwalletdescriptor, and Core's listdescriptors and
exportwatchonlywallet already provide public descriptors.

We are pre-1.0, so delete public API that no command or tool calls
instead of maintaining it:

- core_descriptors, the WalletPublicDeriver protocol, the descriptor
  checksum (DESCSUM) and record helpers, and the Core adapter's
  public_descriptors, gethdkeys and derivehdkey calls;
- generate_core_lightning_secret and CreationCeremony.core_lightning,
  which created fresh Core Lightning secrets that no command creates,
  and the CL padding check only fresh CL generation reached. Parsing,
  recovering, deriving and re-sharing an existing cl secret are
  unchanged.

The real-Core fixture and installed-wheel smoke test now check xprv and
tprv serialization through master_xprv. The package exports 22 names.
The installed package drops from 5,196 to 4,965 logical lines.

Fixes #128
Refs #63

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
Fresh Core Lightning generation was removed from the public API, but the architecture, capability table, identifier policy, and security model still described it as supported. Align those contracts with the remaining behavior: existing CL secrets may still be parsed, recovered, corrected, derived, and re-shared.\n\nRefs #128
Core Lightning imports a codex32 HSM secret only when its threshold is 0
and its index is S; lightningd rejects anything else with "This is only
one share of codex32!". The cl profile still parsed shares and shared S
strings, CreationCeremony.from_secret split CL secrets, and the generic
façade recovered and derived CL shares, so every CL share this library
made or accepted was unusable in Core Lightning.

Reject a nonzero threshold in the cl profile, which closes CL recovery,
derivation and splitting at the parse boundary. The profile hook now
receives the whole header instead of only the share index. Ceremonies
accept only MasterSeed, so their profile plumbing goes away. Tests that
only needed a valid CL secret use the BIP-93 cl10peev vector; the CL
sharing fixtures and tests are removed, and new tests cover the
rejections. The docs no longer promise CL sharing.

Package size goes from 4,965 to 4,959 logical lines.

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
The identifier policy said a random identifier does not make a weak
supplied seed safe. Nothing suggests it would; the sentence only invites
the question.

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
The v1 rewrite dropped the license headers that master carries in
bech32.py and checksums.py. bech32.py still derives convertbits from
Pieter Wuille's segwit_addr.py, and checksums.py keeps his polymod
arithmetic and Leon Olsson Curr and Pearlwort Sneed's codex32
generators. MIT and BSD-3-Clause both require the notice to travel with
the code, and CONTRIBUTING.md requires the original author's header on
derived work.

Restore master's headers, except that checksums.py now credits the
polymod arithmetic, since it no longer holds Bech32/Bech32m constants.
Each credit also names its upstream source, sipa/bech32's
ref/python/segwit_addr.py or BIP-93, as CONTRIBUTING.md asks. Comments
do not count toward the package line budget.

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
The one-shot signature in api.md omitted generate_master_seed's
fingerprint argument. A fresh call that leaves identifier unset raises
ValueError unless that callable is supplied, so the documented defaults
could not generate a seed. Show the argument and its contract.

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
WorksheetCorrection had the same repr leak as CorrectionEdit: for an
erasure the worksheet filled with q, the addend is the recovered
character itself, and for any other position it is the true character
XOR the written one. Leave addend out of the generated repr; field
access, equality and the CLI's explicit display are unchanged.

Tighten the regression to compare exact reprs and to check that the
repaired payload text does not appear.

Refs #129

Claude-Session: https://claude.ai/code/session_01T233rKgZqE5wzDm3EVTHL1
The per-case CSV and kernel JSON (~9,900 lines) are generated records of
an interrupted run that promoted no timing guarantee, and nothing in the
package, tests or tools reads them. Keep the summary in
alignment-benchmarks.md as informational guidance for setting correction
limits on slower devices, drop its run-condition and source-hash details,
point to the history for the raw JSON, and stop shipping docs
*.csv/*.json in the sdist.

Claude-Session: https://claude.ai/code/session_01MDsbGqZmvVThoJrs4vzc4K
Remove code from the substitution and erasure decoder that cannot change
a result.

Every BCH correction was re-checked against the full residue. The check
cannot fail. The generator is the product of the distinct minimal
polynomials of the 8 consecutive roots. GF(32) values that clear those
syndromes also clear the conjugate roots, so the generator divides the
corrected word. The linear erasure solver already rejects inconsistent
systems. Delete _corrections_reach_target.

The linear solver ran after a failed BCH decode even with at most 8
erasures. In that case an erasure-only solution leaves the Forney
syndromes zero, so BCH would already have found it. Call the solver only
when the erasures exceed the BCH roots. The worksheet path now makes the
same choice inline, so _error_corrections is gone. Its word-length and
substitution-limit parameters were unused.

The precomputed erasure-product tables were never built. Remove that
plumbing from _locator_poly, _bch_syndrome_corrections, _repair_body and
_FixedCorrector. Also drop the no-op "except TypeError: raise" clauses.

Keep the direct small-locator solve. Replacing it with Berlekamp-Massey
for every call returned identical results but made the bounded indel
search about 15% slower, which could change truncation under the ten-
second deadline.

Validation: full pytest in normal and -O modes; differential_correction
and differential_wallet --verify; verify_correction_constants; ruff
check, ruff format --check and mypy. An offline comparison against the
previous module found identical results for random BCH syndromes,
damaged ms strings with up to 14 errors or erasures, and worksheet
residues with up to 15 erasures.
Old topic branches can retain superseded contribution rules, as happened while addressing PR #144 after #152 merged. Require agents to consult the current target-branch contributor guide and AI policy before acting on a PR.

State that the tool-neutral policy permits AI-written descriptions and review replies while keeping publication within the user-authorized scope. The maintainer explicitly approved this AGENTS.md patch.

Validation: reviewed the exact approved patch, checked referenced local paths, and ran git diff --check. Documentation only; application tests are not applicable. Refs #144 and #152.
`correct` and the "Possible correction" prompt in secret, share, wallet
and create --existing showed only the repair. After the YES gate, print
one line to stderr first, "Invalid: <reason>", using the first parse
error the caller already caught, so nothing is parsed twice. The
`reason` argument is keyword-only so it can't be swapped silently.

A mixed-case string now says codex32 strings are all uppercase or all
lowercase, and only that case alone doesn't change the encoded data: the
same entry may also hold a wrong symbol, so the reason is not a full
diagnosis. create --existing uses the same wording as the other commands.

Closes #85

Claude-Session: https://claude.ai/code/session_015CuLXqAvAovfoVcUmmogwa
Claude-Session: https://claude.ai/code/session_01Q1TNm1YeYW8K9W2eBvxmCD
@BenWestgate
BenWestgate force-pushed the claude/new-issue-fixes-fvhbl3-85 branch from 65a886a to ec065a3 Compare October 22, 2026 03:13

Copy link
Copy Markdown
Owner Author

Closing as not planned. When a correction is offered, the reason is almost always "The checksum does not match.", which the user already knows, and correct already highlights every changed character. Worse, a reason line can anchor the user on one explanation (for example a wrong share index after 11 or 12 erasures) and lead them to skip the full comparison with their backup, which is the only real protection against a wrong correction.

The tester's case question is answered in the user guide by #97: either case gives the same seed and fingerprint.


Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cli Command-line interface behavior. correction Correction engine and correction UX.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants